/******************************************************************/
/*                                                                */
/*  Winpooch : Windows Watchdog                                   */
/*  Copyright (C) 2004-2005  Benoit Blanchon                      */
/*                                                                */
/*  This program is free software; you can redistribute it        */
/*  and/or modify it under the terms of the GNU General Public    */
/*  License as published by the Free Software Foundation; either  */
/*  version 2 of the License, or (at your option) any later       */
/*  version.                                                      */
/*                                                                */
/*  This program is distributed in the hope that it will be       */
/*  useful, but WITHOUT ANY WARRANTY; without even the implied    */
/*  warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR       */
/*  PURPOSE.  See the GNU General Public License for more         */
/*  details.                                                      */
/*                                                                */
/*  You should have received a copy of the GNU General Public     */
/*  License along with this program; if not, write to the Free    */
/*  Software Foundation, Inc.,                                    */
/*  675 Mass Ave, Cambridge, MA 02139, USA.                       */
/*                                                                */
/******************************************************************/


/******************************************************************/
/* Build configuration                                            */
/******************************************************************/

#define	TRACE_LEVEL	2


/******************************************************************/
/* Includes                                                       */
/******************************************************************/

// module's interface
#include "HookReg.h"

// standard headers
#include <windows.h>
#include <tchar.h>

// project's headers
#include "Assert.h"
#include "Hooks.h"
#include "SpyDllInt.h"
#include "Strlcpy.h"
#include "Trace.h"


/******************************************************************/
/* Internal macros                                                */
/******************************************************************/

//#define SHARED __attribute__((section(".shr"), shared))


/******************************************************************/
/* Internal constants                                             */
/******************************************************************/

#define MAX_KEY_PATH		1024


/******************************************************************/
/* Internal data types                                            */
/******************************************************************/

// empty


/******************************************************************/
/* Internal data                                                  */
/******************************************************************/

// empty 


/******************************************************************/
/* ntdll's stuffs                                                 */
/******************************************************************/

#define KeyNameInformation 3

typedef struct {
  ULONG  NameLength;
  WCHAR  Name[1] ;  
} KEY_NAME_INFORMATION ;


NTSTATUS WINAPI NtQueryKey (HANDLE, ULONG, PVOID, ULONG, PULONG) ;


/******************************************************************/
/* Internal function                                              */
/******************************************************************/

LPTSTR HookReg_ChangePrefix (LPTSTR szPath, LPCTSTR szPrefix, LPCTSTR szNewPrefix)
{
  if( _tcsnicmp(szPath, szPrefix, _tcslen(szPrefix)) )
    return NULL ;

  szPath += _tcslen(szPrefix) - _tcslen(szNewPrefix) ;
  
  _tcsncpy (szPath, szNewPrefix, _tcslen(szNewPrefix)) ;
  
  return szPath ;
}


/******************************************************************/
/* Internal function                                              */
/******************************************************************/

LPTSTR HookReg_ShortenKeyPath (LPTSTR szKeyPath)
{
  LPTSTR szNewKeyPath ;

  szNewKeyPath = HookReg_ChangePrefix (szKeyPath, 
				       TEXT("\\Registry\\Machine\\"),
				       TEXT("HKLM\\")) ;
  if( szNewKeyPath ) return szNewKeyPath ;
  
  szNewKeyPath = HookReg_ChangePrefix (szKeyPath, 
				       TEXT("\\Registry\\User\\"),
				       TEXT("HKU\\")) ;
  if( szNewKeyPath ) return szNewKeyPath ;

  return szKeyPath ;
}


/******************************************************************/
/* Exported function :                                            */
/******************************************************************/

LONG WINAPI Hook_NtSetValueKey (HANDLE	KeyHandle,
				PUNICODE_STRING	ValueName,
				ULONG	TitleIndex,
				ULONG	Type,
				PVOID	Data,
				ULONG	DataSize) 
{
  {
    BYTE	pBuffer[1024] ;
    ULONG	nSize ;
    NTSTATUS	nResult ;
    
    LPTSTR	szKeyPath ;
    DWORD	nReaction ;
    
    TRACE ;

    nResult = NtQueryKey (KeyHandle, KeyNameInformation, 
			  pBuffer, sizeof(pBuffer)-2, &nSize) ;

    if( nResult==STATUS_SUCCESS )
      {
	szKeyPath = ((KEY_NAME_INFORMATION*)pBuffer)->Name ;
	szKeyPath[((KEY_NAME_INFORMATION*)pBuffer)->NameLength/2] = 0 ;

	szKeyPath = HookReg_ShortenKeyPath (szKeyPath) ;

	TRACE_INFO (TEXT("Key = %s\n"), szKeyPath) ;
      }
    else szKeyPath = NULL ;
      

    if( szKeyPath )
      {
	// log call
	nReaction = SpyInt_CatchCall (REASON_REG_SETVALUE, TEXT("ss"), 
				      szKeyPath, ValueName->Buffer) ;
      }
    else 
      {
	nReaction = RULE_ACCEPT ;    
      }
    
    if( nReaction == RULE_REJECT ) return ERROR_ACCESS_DENIED ; 
    if( nReaction == RULE_FEIGN ) return ERROR_SUCCESS ;     
  }

  JUMP_TO_STUB (HOOKS_NTSETVALUEKEY) ;
  ASSERT (0) ;
  return 0 ;
}
